﻿#region

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows.Controls;
using System.Windows.Data;
using GalaSoft.MvvmLight.Command;
using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.Workflow;
using Rio.Applications.Web.Services;
using Rio.Framework.Pages.AppCode.Helpers;
using Rio.Framework.Pages.ChildWindows;
using Rio.Framework.Pages.Context;
using Rio.Framework.Pages.Events;
using Rio.Framework.Pages.Helpers.Converter;
using Rio.Framework.Pages.Manager;
using Rio.Framework.Pages.Workflow.Models;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data;

#endregion

namespace Rio.Framework.Pages.Workflow.BaseClass
{

    #region Delegates

    public delegate void DisplayWorkflowInstanceListEventHandler(object sender, DisplayWorkflowInstanceListEventArgs args);

    #endregion

    public class WorkflowInstanceListBase : UserControl, INotifyPropertyChanged
    {
        #region Fields

        protected const int startIndexInsertCounter = 4;
        protected LoadingIndicatorManager _busyIndicator;
        protected DataItemTreeView _selectedDataItemTreeView;
        protected ObservableCollection<WorkflowInstance> _selectedWorkflowInstances;
        protected Queue<WorkflowInstance> _selectedWorkflowInstancesToDelete = new Queue<WorkflowInstance>();
        protected QueryableCollectionView _workflowInstances;

        #endregion

        #region Instance Properties

        public DataItemTreeView CurrentDataItemTreeView
        {
            get
            {
                return _selectedDataItemTreeView;
            }
        }

        public RelayCommand<string> FlowActionPerfomedCommand { get; set; }

        public ObservableCollection<WorkflowInstance> SelectedWorkflowInstances
        {
            get
            {
                return _selectedWorkflowInstances;
            }
            set
            {
                _selectedWorkflowInstances = value;
                OnPropertyChanged("SelectedWorkflowInstances");
                FlowActionPerfomedCommand.RaiseCanExecuteChanged();
            }
        }

        public QueryableCollectionView WorkflowInstances
        {
            get
            {
                return _workflowInstances;
            }
            set
            {
                _workflowInstances = value;
                OnPropertyChanged("WorkflowInstances");
            }
        }

        #endregion

        #region Instance Methods

        /// <summary>
        ///   Sets the grid view row as read.
        /// </summary>
        protected virtual void SetGridViewRowAsRead()
        {
        }

        /// <summary>
        ///   Deletes the workflow instance.
        /// </summary>
        /// <param name="workflowInstanceToDelete"> The workflow instance to delete. </param>
        protected void DeleteWorkflowInstance(WorkflowInstance workflowInstanceToDelete)
        {
            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;

            switch (_selectedDataItemTreeView.ItemType)
            {
                case WorkflowTreeItemType.Reception:

                    businessEntitiesDomainContext.DeleteUserInstance(
                        workflowInstanceToDelete.InstanceUserId,
                        DeleteWorkflowMessagesCallback,
                        workflowInstanceToDelete);
                    break;
                case WorkflowTreeItemType.Send:

                    businessEntitiesDomainContext.DeleteInstance(
                        workflowInstanceToDelete.Identifier,
                        DeleteWorkflowMessagesCallback,
                        workflowInstanceToDelete);

                    break;
            }
        }

        /// <summary>
        ///   Deletes the workflow messages callback.
        /// </summary>
        /// <param name="result"> The result. </param>
        protected void DeleteWorkflowMessagesCallback(InvokeOperation<ReturnBoolean> result)
        {
            SplashScreenManager.Stop(this);

            if (!result.HasError && result.Value.Value)
            {
                if (_selectedWorkflowInstancesToDelete.Count == 0)
                {
                    OnWorkflowInstanceListDeleted();
                }
                else
                {
                    DeleteWorkflowInstance(_selectedWorkflowInstancesToDelete.Dequeue());
                }
            }
        }

        /// <summary>
        ///   Get the type of an index
        /// </summary>
        /// <param name="p_oIndex"> </param>
        /// <returns> </returns>
        protected Type GetIndexType(Index p_oIndex)
        {
            Type l_oType;
            switch (p_oIndex.Type)
            {
                case (int) IndexDomainServiceEnums.IndexType.Date:
                    l_oType = typeof (DateTime?);
                    break;
                case (int) IndexDomainServiceEnums.IndexType.Integer:
                    l_oType = typeof (string); // string because filtering no run with integer and string value
                    break;
                case (int) IndexDomainServiceEnums.IndexType.Double:
                    l_oType = typeof (Double);
                    break;
                case (int) IndexDomainServiceEnums.IndexType.Boolean:
                    l_oType = typeof (bool);
                    break;
                default:
                    l_oType = typeof (string);
                    break;
            }
            return l_oType;
        }

        /// <summary>
        ///   Called when [property changed].
        /// </summary>
        /// <param name="propertyName"> Name of the property. </param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        ///   Called when [workflow instance displaying].
        /// </summary>
        protected void OnWorkflowInstanceDisplaying(Folder folder, WorkflowInstance instance)
        {
            if (WorkflowInstanceDisplaying != null)
            {
                WorkflowInstanceDisplaying(this, new DisplayWorkflowInstanceListEventArgs(CurrentDataItemTreeView, folder, instance));
            }
        }

        /// <summary>
        ///   Called when [workflow instance deleted].
        /// </summary>
        protected void OnWorkflowInstanceListDeleted()
        {
            if (WorkflowInstanceListDeleted != null)
            {
                WorkflowInstanceListDeleted(this, new EventArgs());
            }
        }

        /// <summary>
        ///   Called when [workflow instance refresh].
        /// </summary>
        protected void OnWorkflowInstanceListRefreshed()
        {
            if (WorkflowInstanceListRefreshed != null)
            {
                WorkflowInstanceListRefreshed(this, new EventArgs());
            }
        }

        /// <summary>
        ///   Opens the remind child window.
        /// </summary>
        protected void OpenRemindChildWindow()
        {
            RemindWindow remindWindow = new RemindWindow(SelectedWorkflowInstances.First());
            remindWindow.Closed += remindWindow_Closed;

            remindWindow.ShowDialog();
        }

        /// <summary>
        /// Adds the folder index columns to grid.
        /// </summary>
        /// <param name="folderType">Type of the folder.</param>
        /// <param name="gridView">The grid view.</param>
        /// <param name="addInFirst">if set to <c>true</c> [add in first].</param>
        protected void AddFolderIndexColumnsToGrid(FolderType folderType, GridViewDataControl gridView, bool addInFirst = false)
        {
            int currentIndexCounter = startIndexInsertCounter;
            foreach (var index in folderType.LstIndex)
            {
                if (index.IsVisible)
                {
                    if (addInFirst)
                    {
                        gridView.Columns.Insert(currentIndexCounter,
                                                new GridViewDataColumn
                                                    {
                                                        UniqueName = "IDX" + index.Indentifier.ToString(),
                                                        Header = index.IndexLabel,
                                                        IsReadOnly = true,
                                                        DataType = GetIndexType(index),
                                                        DataFormatString =
                                                            GetIndexType(index) == typeof (DateTime?) ? DateStringFormatterHelper.GetDateStringFormatter() : "",
                                                        DataMemberBinding =
                                                            new Binding(String.Format("FolderIndex[index{0}]", index.Indentifier)) {Converter = new IndexValueConverter()}
                                                    });

                        currentIndexCounter++;
                    }
                    else
                    {
                        gridView.Columns.Add(
                            new GridViewDataColumn
                            {
                                UniqueName = index.Indentifier.ToString(),
                                Header = index.IndexLabel,
                                IsReadOnly = true,
                                DataType = GetIndexType(index),
                                DataFormatString =
                                    GetIndexType(index) == typeof(DateTime?) ? DateStringFormatterHelper.GetDateStringFormatter() : "",
                                DataMemberBinding =
                                    new Binding(String.Format("FolderIndex[index{0}]", index.Indentifier)) { Converter = new IndexValueConverter() }
                            });
                    }
                }
            }
        }

        #endregion

        #region Event Handling

        /// <summary>
        ///   Handles the Closed event of the remindWindow control.
        /// </summary>
        /// <param name="sender"> The source of the event. </param>
        /// <param name="e"> The <see cref="Telerik.Windows.Controls.WindowClosedEventArgs" /> instance containing the event data. </param>
        protected void remindWindow_Closed(object sender, WindowClosedEventArgs e)
        {
            RemindWindow remindWindowSource = sender as RemindWindow;
            if (remindWindowSource != null)
            {
                remindWindowSource.Closed -= remindWindow_Closed;
            }
        }

        #endregion

        #region Event Declarations

        public event DisplayWorkflowInstanceListEventHandler WorkflowInstanceDisplaying;
        public event EventHandler WorkflowInstanceListDeleted;
        public event EventHandler WorkflowInstanceListRefreshed;

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

    #region Enums

    public enum WorkflowInstanceListMode
    {
        Normal = 0,
        Administration = 1
    }

    #endregion

    #region Class

    public class DisplayWorkflowInstanceListEventArgs
        : EventArgs
    {
        #region Constructors

        public DisplayWorkflowInstanceListEventArgs(DataItemTreeView currentDataItemTreeView, Folder folder, WorkflowInstance workflowInstance)
        {
            CurrentDataItemTreeView = currentDataItemTreeView;
            Folder = folder;
            WorkflowInstance = workflowInstance;
        }

        #endregion

        #region Instance Properties

        public DataItemTreeView CurrentDataItemTreeView { get; set; }
        public Folder Folder { get; set; }
        public WorkflowInstance WorkflowInstance { get; set; }

        #endregion
    }

    #endregion
}